"""
PyMak rules and actions to copy files.

See documentation on the 'targets_to_copy_existing_files' function.
"""

# Python imports
import os
import sys
import shutil
import filecmp
import logging
import re

# PyMak imports
import pymak
from pymak.path import to_path



MAJOR_VERSION = 1
MINOR_VERSION = 0

def init(context):
    """This method sets up into the provided PyMak context the following:

    CopyAction.

    """
    
    context.declare_action('.copy', CopyAction())

    
def version_ok(major, minor):
    if major != MAJOR_VERSION:
        return False
    if minor > MINOR_VERSION:
        return False
    return True


def targets_to_copy_existing_files(context,
                                   from_dir, to_dir,
                                   variants,
                                   pattern=None,
                                   excludes=None):
    """This function creates source and destination targets to enable
    copying files from one location to another. Clearly all the files
    that need to be copied should exist at the time this function is
    called - therefor this function is not suitable for distributing
    files that are made as part of the build process.

    The 'context' is the PyMak context in which the targets will be
    added.

    The 'from_dir' and 'to_dir' are the directories (string or path
    objects) describing the source and destination. This function
    walks over all the files under 'from_dir' creating targets for
    each file found there.  Destination targets are created with the
    CopyAction set on them.

    The 'variants' list describes the variants that the destination
    targets should implement. This allows variables in the path names
    specified in the destination paths to be expanded appropriately.

    The 'pattern' argument is passed directly through to the path.walk
    method - see documentation there.

    The 'excludes' is either a Regular Expression object or a string
    which will be compiled into a regular expression object. Any file
    or directory which matches this regular expression will be
    skipped.
    
    The list of destination targets is returned.
    """
    targets = []
    if excludes:
        if isinstance(excludes, basestring):
            excludes = re.compile(excludes)

    from_dir = to_path(from_dir)
    to_dir = to_path(to_dir)

    strip = len(from_dir.splitall())

    for f in from_dir.walk(pattern):
        if excludes and excludes.match(f):
            continue
        if f.isfile():
            from_t = context.target(f, rule=None)
            p = f.splitall()[strip:]
            result = to_dir.joinpath(*p)
            to_t = context.target(result,
                                  rule=None,
                                  variants=variants,
                                  action='.copy',
                                  depends_on=from_t)
            targets.append(to_t)

    return targets

class CopyAction(pymak.Action):
    """This simple action will copy the file specified by the first dependent of the
    target to the name of the file of the target.
    """
    def execute_action(self, t, variant_values):
        try:
            srcFile = t.list_of_sub_targets(variant_values)[0].path
            destFile = t.path
            logging.warning("%s..." % t.path)
            logging.info(_("Copying file: '%s' to '%s'"), srcFile, destFile)
            # Copy the file preserving time stamps but not permissions
            pymak.copy_file(srcFile, destFile)
        except OSError, e:
            raise pymak.PyMakException("Failed to copy '%s' to '%s" % (srcFile, destFile),
                                       underlying_exception=e)

